﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Drawing;
using dotnetCHARTING.WinForms;

namespace OEMS
{
    class Visualisatie
    {

        private int[] combinatieGegevensID;
        private Meting[] meting;
        private Chart graph;

        public Visualisatie(Chart chart, Motor motor)
        {
            this.graph = chart;

            this.meting = new Meting[MetingDB.GetMetingenArray(motor.GegevensId).Length];
            this.meting = MetingDB.GetMetingenArray(motor.GegevensId);

            createChart();
        }


        public Visualisatie(Chart chart, Overbrenging overbrenging)
        {
            this.graph = chart;

            this.meting = new Meting[MetingDB.GetMetingenArray(overbrenging.GegevensId).Length];
            this.meting = MetingDB.GetMetingenArray(overbrenging.GegevensId);

            createChart();
        }


        public Visualisatie(Chart chart, Belasting belasting)
        {
            this.graph = chart;

            this.meting = new Meting[MetingDB.GetMetingenArray(belasting.GegevensId).Length];
            this.meting = MetingDB.GetMetingenArray(belasting.GegevensId);

            createChart();

        }


        //public Visualisatie(Chart chart, Combinatie combinatie)
        //{
        //    this.combinatieGegevensID = new int[3];
        //    this.combinatieGegevensID[0] = combinatie.MotorGegevensId;
        //    this.combinatieGegevensID[1] = combinatie.OverbrengingGegevensId;
        //    this.combinatieGegevensID[2] = combinatie.BelastingGegevensId;

        //    this.chart = chart;
        //    this.combinatie = combinatie;
        //}




        /// <summary>
        /// Methode die de grafiek 
        /// </summary>
        /// <param name="gegevensID">a</param>
        /// <author>Mathieu Cruts</author>
        public void createChart()
        {
            SeriesCollection seriesCollection = new SeriesCollection();
            Series series = new Series();

            // CONFIGURE
            setGraphSettings(graph);

            // IMPORT DATA
            seriesCollection = importAndAddData();

            // COLOR PALETTE
            createColorPalette(graph, seriesCollection);

            // ADD DATA
            graph.SeriesCollection.Add(seriesCollection);

            // ADD CONTOUR
            series = addContour(series);
            graph.SeriesCollection.Add(series);

        }


        private void setGraphSettings(Chart graph)
        {

            graph.Width = 1024;
            graph.Height = 600;
            graph.MarginTop = 60;
            graph.LegendBox.Visible = false;
            graph.Type = ChartType.Surface;
            //coloring while knowing the values around the current cell)
            graph.DefaultSeries.InterpolationFillFactor = 5;

            graph.XAxis.Interval = Convert.ToDouble(Properties.Settings.Default.xAxisInterval);
            graph.YAxis.Interval = Convert.ToDouble(Properties.Settings.Default.yAxisInterval);

        }



        /// <summary>
        /// Method die alle data importeert voor de grafiek
        /// </summary>
        /// <param name="gegevensID">a</param>
        /// <author>Mathieu Cruts</author>
        private SeriesCollection importAndAddData()
        {
            SeriesCollection SC = new SeriesCollection();
            Series series;

            double[] xValues = getXValues(meting);
            double[] yValues = getYValues(meting);
            double [][] zValues = getZValues(meting);

            // Geeft de data aan een serie door, die op zijn beurt wordt doorgegeven aan de seriescollectie
            series = Series.FromSurfaceData("", xValues, yValues, zValues);

            SC.Add(series);

            //transparency of our grid
            SC[0].Line.Transparency = 65;

            return SC;
        }


        private double[] getXValues(Meting[] metingen)
        {
            double[] xVals = new double[1764];

            for (int i = 0; i < metingen.Length; i++)
            {
                xVals[i] = Convert.ToDouble(metingen[i].Moment);

            }

            xVals = readByColumn(getDistinctKoppel(xVals), 21);

            return xVals;

        }


        private double[] getYValues(Meting[] metingen)
        {
            double[] yVals = new double[1764];

            for (int i = 0; i < metingen.Length; i++)
            {
                yVals[i] = Convert.ToDouble(metingen[i].Toerental);

            }

            return yVals;
        }


        private double[][] getZValues(Meting[] metingen)
        {
            double[][] zVals = new double[42][];
            int counter = 0;

            for (int i = 0; i < Math.Sqrt(metingen.Length); i++)
            {
                zVals[i] = new double[42];

                for (int j = 0; j < Math.Sqrt(metingen.Length); j++)
                {
                    zVals[i][j] = Convert.ToDouble(metingen[counter].Rendement);
                    counter++;
                }
            }

            return zVals;
        }


        /// <summary>
        /// De dubbels van kolom A tot V worden éénmaal ingelezen, gevolgd door alle andere waarden
        /// </summary>
        /// <param name="koppelArray">array met alle data</param>
        /// <author>Mathieu Cruts</author>
        private double[] getDistinctKoppel(double[] koppelArray)
        {
            double[] data = new double[882];
            int counter = 0;

            for (int i = 21; i < koppelArray.Length; i++)
            {
                if ((i / 21) % 2 == 1)
                {
                    for (int j = 0; j < 21; j++)
                    {
                        data[counter] = koppelArray[(i + j)];
                        counter++;
                    }

                    i += 21;
                }

            }
            return data;
        }


        /// <summary>
        /// Gegevens uit een array worden omgevormd alsof ze kolom per kolom werden ingelezen ipv rij per rij
        /// </summary>
        /// <param name="koppelArray">array met de data</param>
        /// <param name="columnAmount">aantal kolommen waarin de data verdeeld moet worden</param>
        /// <author>Mathieu Cruts</author>
        private double[] readByColumn(double[] koppelArray, int columnAmount)
        {
            int counter = 0;
            List<double> list = new List<double>();
            list.Add(koppelArray[0]);

            for (int i = 0; i < columnAmount; i++)
            {
                counter = i;

                do
                {
                    list.Add(koppelArray[counter]);
                    System.Diagnostics.Debug.WriteLine(koppelArray[counter]);
                    counter += columnAmount;

                } while (counter < koppelArray.Length);
            }

            return list.ToArray();
        }




        private void createColorPalette(Chart chart, SeriesCollection seriesCollection)
        {
            int amountOfColors = Properties.Settings.Default.GraphColors.Count;

            // Sets a palette of colors and adds it to our seriescollection
            chart.SmartPalette = seriesCollection[0].GetSmartPalette(ElementValue.ZValue, getColorArrayFromSettings(amountOfColors));

            // Creates a bar with the used colors and their starting values + adds it to the chart
            Annotation an = new Annotation(createColorPalette(900, chart.SmartPalette, amountOfColors, true));
            an.Position = new Point(25, 10);
            an.DynamicSize = false;
            chart.Annotations.Add(an);
        }


        private Color[] getColorArrayFromSettings(int length)
        {
            Color[] colorArray = new Color[length];
            Color kleur;

            for (int i = 0; i < length; i++)
            {
                try
                {
                    kleur = new Color();
                    kleur = Color.FromName(Properties.Settings.Default.GraphColors[i]);
                    colorArray[i] = kleur;
                }
                catch (Exception)
                {
                    MessageBox.Show("Kleurconversie fout", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }

            }

            return colorArray;
        }


        /// <summary>
        /// Creeert een kleurenpalette om boven de grafiek weer te geven
        /// </summary>
        /// <param name="width">breedte van het gehele kleurenpalette</param>
        /// <param name="smartPalette">smartpalette met de kleuren en waardes</param>
        /// <param name="divisions">aantal verdelingen</param>
        /// <param name="withValues">al dan niet de overgangen van de waardes weergeven</param>
        /// <author>dotnetcharting</author>
        private String createColorPalette(int width, SmartPalette smartPalette, int divisions, bool withValues)
        {
            // Get Maximum Value of the smart palette range
            double max = (double)smartPalette.GetScaleRange("*").ValueHigh;
            double min = (double)smartPalette.GetScaleRange("*").ValueLow;

            string colorHtmlString = "", spacerString = "";
            double step = (max - min) / divisions;

            // Width of each division.
            int boxWidth = width / divisions;

            // Generate swatch string for each division.
            for (int i = 0; i < divisions; i++)
            {
                spacerString += "<Chart:Spacer size='" + boxWidth + "x1'>";

                // Get the color of the current division.
                string color = getHTMLColor(smartPalette.GetValueColor("", min + (i * (step))));

                if (withValues)
                {
                    double value = Math.Round((min + (i * (step))), 2);
                    double nextValue = Math.Round(((value + step) - 1), 2);

                    if (value < 0)
                    {
                        value = 0;
                    }

                    colorHtmlString += "<block hAlignment='Center' bgColor='" + color + "'>" + value + "  -  " + nextValue + " ";
                }
                else
                {
                    colorHtmlString += "<block bgColor='" + color + "' fColor='" + color + "'>_";
                }

            }

            //return the swatch string.
            return spacerString + "<row>" + colorHtmlString;
        }


        /// <summary>
        /// Kleuren worden geconverteerd naar hun hexadecimale HTML-waarde
        /// </summary>
        /// <param name="color">de om te vormen kleur</param>
        /// <author>dotnetcharting</author>
        private string getHTMLColor(Color color)
        {
            return "#" + color.R.ToString("X2") + color.G.ToString("X2") + color.B.ToString("X2"); // X2 maakt er 2 getallen van zodat het geheel een hexadecimale HTML-code wordt
        }



        private Series addContour(Series series)
        {
            // We add an additional series with no data to layer an additional layer style (contour)
            series.Type = SeriesTypeSurface.Contour;
            series.Background.Transparency = 80;
            series.Line.Color = Color.Black;
            series.Line.Transparency = 70;

            return series;
        }





        public void saveGraphOnComputer(Chart chart, String fileName)
        {
            FolderBrowserDialog folderDlg = new FolderBrowserDialog();
            Bitmap bmp;
            DialogResult result;
            String fullPath;

            folderDlg.ShowNewFolderButton = true;

            result = folderDlg.ShowDialog();

            if (result == DialogResult.OK)
            {
                chart.TempDirectory = folderDlg.SelectedPath;
                fullPath = folderDlg.SelectedPath + "/" + fileName;
                chart.ImageFormat = dotnetCHARTING.WinForms.ImageFormat.Bmp;

                bmp = chart.GetChartBitmap();
                bmp.Save(fullPath, System.Drawing.Imaging.ImageFormat.Bmp);
            }
        }


        public Bitmap saveGraphAsBitmap(Chart chart)
        {
            Bitmap bmp = chart.GetChartBitmap();
            return bmp;

        }


    }
}
